import 'dart:convert';
import 'dart:math';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import '../utils/websocket.dart';
import '../utils/sputil.dart';

enum WebSocketState {
  ConnectionOpen,
  ConnectionClosed,
  ConnectionError,
}

class WebSocketProvider {
// 单例公开访问点
  factory WebSocketProvider() => _sharedInstance();

  // 静态私有成员，没有初始化
  static WebSocketProvider _instance = WebSocketProvider._();

  // 私有构造函数
  WebSocketProvider._() {
    // 具体初始化代码
    connect();
    print("WebSocketProvider 私有构造函数");
  }

  // 静态、同步、私有访问点
  static WebSocketProvider _sharedInstance() {
    return _instance;
  }

  SimpleWebSocket? _socket;
  String? username;
  String? name;
  var spu = SpUtil();

  late WebSocketState state;

  JsonEncoder _encoder = JsonEncoder();
  JsonDecoder _decoder = JsonDecoder();

  Function(WebSocketState state)? onStateChange;
  Function(dynamic event, dynamic data)? onMessageEvent;

  Function(Map data)? onChat;
  Function(List<dynamic> data)? onPeers;

  /// 接入websocket
  Future<void> connect() async {
    var url = 'https://rtc.jxt.elef.top:8086/ws';
    _socket = SimpleWebSocket(url);

    username = spu.get<String>("username");
    name = spu.get<String>("name");

    _socket?.onOpen = () {
      print('onOpen');
      onStateChange?.call(WebSocketState.ConnectionOpen);
      state = WebSocketState.ConnectionOpen;

      _send('new', {'name': name, 'id': username, 'user_agent': "pc"});
    };

    _socket?.onMessage = (message) {
      print('Received data: ' + message);
      onMessage(_decoder.convert(message));
    };

    _socket?.onClose = (int? code, String? reason) {
      print('Closed by server [$code => $reason]!');
      state = WebSocketState.ConnectionClosed;
      onStateChange?.call(WebSocketState.ConnectionClosed);
    };

    await _socket?.connect();
  }

  Future<void> chat(dynamic data) async {
    if (state != WebSocketState.ConnectionOpen) {
      await connect();
    }

    _send("chat", data);
  }

  _send(event, data) {
    var request = Map();
    request["type"] = event;
    request["data"] = data;
    var jsonData = _encoder.convert(request);

    print("----------_send");

    _socket?.send(jsonData);
  }

  void onMessage(message) async {
    Map<String, dynamic> mapData = message;
    var data = mapData['data'];
    var event = mapData["type"];

    onMessageEvent?.call(event, data);

    switch (mapData['type']) {
      case 'peers':
        onPeers?.call(data);
        break;
      case 'chat':
        onChat?.call(data);
    }
  }
}
